#include "sync_folders_command.h"
#include "service/backend_service.h"
#include "../database/database_manager.h"
#include "command_executor.h"
#include <QDebug>
#include <QUrl>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonParseError>
#include <QStandardPaths>
#include <QDir>
#include <QSettings>
#include <QFile>

SyncFoldersCommand::SyncFoldersCommand(QObject *parent)
    : BaseCommand(parent)
    , m_pendingDiskId("")
{
}

SyncFoldersCommand::~SyncFoldersCommand()
{
}

void SyncFoldersCommand::setNetworkAccessManager(QNetworkAccessManager *networkManager)
{
    // 如果之前已经设置了 networkManager，先断开旧的连接
    if (m_networkManager) {
        disconnect(m_networkManager, &QNetworkAccessManager::finished,
                   this, &SyncFoldersCommand::handleSyncFoldersResponse);
    }
    
    BaseCommand::setNetworkAccessManager(networkManager);
    
    // 连接网络请求完成信号
    if (m_networkManager) {
        connect(m_networkManager, &QNetworkAccessManager::finished,
                this, &SyncFoldersCommand::handleSyncFoldersResponse);
    }
}

bool SyncFoldersCommand::execute(const QString &diskIdOrFolderId)
{
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: BackendService 或 QNetworkAccessManager 未设置";
        emit syncFoldersCompleted(-1, "BackendService 或 QNetworkAccessManager 未设置");
        return false;
    }
    
    if (diskIdOrFolderId.isEmpty()) {
        qDebug() << "SyncFoldersCommand: 网盘ID为空";
        emit syncFoldersCompleted(-1, "网盘ID为空");
        return false;
    }
    
    // 检查是否有accessToken，如果没有则先获取
    if (!ensureAccessToken()) {
        // 如果没有选中的公司ID，无法获取accessToken
        if (!m_backendService || m_backendService->loadSelectedCompanyId().isEmpty()) {
            qDebug() << "SyncFoldersCommand: 没有选中的公司ID，无法获取accessToken";
            emit syncFoldersCompleted(-1, "没有选中的公司ID，无法获取accessToken");
            return false;
        }
        // 正在获取 token，保存待处理的参数
        m_pendingDiskId = diskIdOrFolderId;
        return true; // 返回true表示已发起获取token的请求
    }
    
    // 获取 accessToken
    QString accessToken = CommandExecutor::getAccessToken();
    
    // 获取 baseUrl
    QString baseUrl = getBaseUrl();
    
    // 构建请求URL
    QString url = buildRequestUrl(baseUrl, diskIdOrFolderId);
    
    qDebug() << "SyncFoldersCommand: 发送同步文件夹请求到:" << url;
    
    // 创建网络请求
    QNetworkRequest request = createRequest(url, "GET", "SyncFoldersCommand/1.0");
    
    // 添加token到请求头
    addTokenToRequest(request, accessToken);
    
    // 发送GET请求
    QNetworkReply *reply = m_networkManager->get(request);
    qDebug() << "SyncFoldersCommand: 发送同步文件夹请求，reply对象:" << reply;
    
    // 设置用户数据，用于识别请求类型
    reply->setProperty("requestType", "syncFolders");
    reply->setProperty("diskId", diskIdOrFolderId);
    
    return true;
}

void SyncFoldersCommand::handleSyncFoldersResponse(QNetworkReply *reply)
{
    // 检查对象是否仍然有效（可能在信号排队期间被销毁）
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: 对象已被销毁，忽略响应";
        if (reply) {
            reply->deleteLater();
        }
        return;
    }
    
    if (!reply) {
        qDebug() << "SyncFoldersCommand: 同步文件夹响应为空";
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit syncFoldersCompleted(-1, "同步文件夹响应为空");
        }
        return;
    }
    
    QString requestType = reply->property("requestType").toString();
    if (requestType != "syncFolders") {
        // 不是同步文件夹请求，忽略
        reply->deleteLater();
        return;
    }
    
    // 打印reply详细信息
    qDebug() << "SyncFoldersCommand: 收到同步文件夹响应，reply对象:" << reply;
    qDebug() << "SyncFoldersCommand: 响应状态码:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "SyncFoldersCommand: 响应头信息:" << reply->rawHeaderPairs();
    
    // 再次检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: 对象已被销毁，忽略响应";
        reply->deleteLater();
        return;
    }
    
    // 检查网络错误
    if (reply->error() != QNetworkReply::NoError) {
        qDebug() << "SyncFoldersCommand: 同步文件夹网络请求错误:" << reply->errorString();
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit syncFoldersCompleted(-1, "网络请求失败: " + reply->errorString());
        }
        reply->deleteLater();
        return;
    }
    
    // 读取响应数据
    QByteArray responseData = reply->readAll();
    qDebug() << "SyncFoldersCommand: 同步文件夹响应数据包:" << responseData;
    qDebug() << "SyncFoldersCommand: 响应数据长度:" << responseData.size() << "字节";
    
    // 解析JSON响应
    QJsonParseError parseError;
    QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
    
    // 再次检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: 对象已被销毁，忽略响应";
        reply->deleteLater();
        return;
    }
    
    if (parseError.error != QJsonParseError::NoError) {
        qDebug() << "SyncFoldersCommand: 同步文件夹JSON解析错误:" << parseError.errorString();
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit syncFoldersCompleted(-2, "响应数据格式错误");
        }
        reply->deleteLater();
        return;
    }
    
    if (!doc.isObject()) {
        qDebug() << "SyncFoldersCommand: 同步文件夹响应数据不是有效的JSON对象";
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit syncFoldersCompleted(-3, "响应数据格式错误");
        }
        reply->deleteLater();
        return;
    }
    
    // 最后一次检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: 对象已被销毁，忽略响应解析";
        reply->deleteLater();
        return;
    }
    
    QJsonObject response = doc.object();
    parseSyncFoldersResponse(response);
    
    reply->deleteLater();
}

void SyncFoldersCommand::parseSyncFoldersResponse(const QJsonObject &response)
{
    // 检查对象是否仍然有效
    if (!isValid()) {
        qDebug() << "SyncFoldersCommand: 对象已被销毁，忽略响应解析";
        return;
    }
    
    // 解析响应字段
    int errcode = response["errcode"].toInt();
    QString errmsg = response["errmsg"].toString();
    
    qDebug() << "SyncFoldersCommand: 同步文件夹结果 - 错误码:" << errcode << "错误消息:" << errmsg;
    
    if (errcode == 0) {
        // 解析文件夹数据
        if (response.contains("data") && response["data"].isArray()) {
            QJsonArray dataArray = response["data"].toArray();
            qDebug() << "SyncFoldersCommand: 同步文件夹 - 获取到文件夹数量:" << dataArray.size();
            
            // 过滤掉null值并发送文件夹数据信号
            QJsonArray validFolders;
            for (int i = 0; i < dataArray.size(); ++i) {
                if (!dataArray[i].isNull()) {
                    validFolders.append(dataArray[i]);
                    qDebug() << "SyncFoldersCommand: 同步文件夹 - 文件夹数据:" << dataArray[i];
                }
            }
            
            // 再次检查对象是否仍然有效
            if (!isValid()) {
                qDebug() << "SyncFoldersCommand: 对象已被销毁，无法处理文件夹数据";
                return;
            }
            
            // 直接同步到数据库
            if (m_databaseManager) {
                m_databaseManager->syncFoldersFromJson(validFolders);
            }
            
            // 同步数据库后，在工作目录创建对应的文件夹
            createFoldersInWorkDirectory(validFolders);
            
            // 最后一次检查对象是否仍然有效
            if (!isValid()) {
                qDebug() << "SyncFoldersCommand: 对象已被销毁，无法发送完成信号";
                return;
            }
            
            // 发送同步完成信号
            emit syncFoldersCompleted(0, "同步文件夹成功，共" + QString::number(validFolders.size()) + "个文件夹");
        } else {
            qDebug() << "SyncFoldersCommand: 同步文件夹 - 响应中没有data字段或data不是数组";
            // 只有在对象仍然有效时才发送信号
            if (isValid()) {
                emit syncFoldersCompleted(-4, "响应数据格式错误：缺少data字段");
            }
        }
    } else {
        qDebug() << "SyncFoldersCommand: 同步文件夹失败:" << errmsg;
        // 只有在对象仍然有效时才发送信号
        if (isValid()) {
            emit syncFoldersCompleted(errcode, errmsg);
        }
    }
}

QString SyncFoldersCommand::buildRequestUrl(const QString &baseUrl, const QString &diskId)
{
    // 每次都同步2级目录
    return baseUrl + QString("/kms/api/kms/sync/folders/%1/fetch-levels/2").arg(diskId);
}


void SyncFoldersCommand::createFoldersInWorkDirectory(const QJsonArray &foldersData)
{
    QString homePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);
    
    // 构建工作目录路径: Home/.myapps/work
    QString workBase = QDir::cleanPath(homePath + "/.myapps/work");
    
    // 确保工作目录存在
    QDir workDir;
    if (!workDir.exists(workBase)) {
        if (!workDir.mkpath(workBase)) {
            qDebug() << "SyncRootFolderCommand: 无法创建工作目录:" << workBase;
            return;
        }
    }
    
    // 遍历文件夹数据，创建对应的文件夹
    int createdCount = 0;
    int skippedCount = 0;
    
    for (const QJsonValue &value : foldersData) {
        if (!value.isObject()) {
            continue;
        }
        
        QJsonObject folderObj = value.toObject();
        
        // 跳过删除标记的文件夹
        bool isDelete = folderObj["delete"].toBool(false);
        if (isDelete) {
            continue;
        }
        
        // 获取文件夹路径和名称
        QString path = folderObj["path"].toString();
        QString name = folderObj["name"].toString();
        
        if (path.isEmpty() || name.isEmpty()) {
            qDebug() << "SyncRootFolderCommand: 文件夹路径或名称为空，跳过";
            skippedCount++;
            continue;
        }
        
        // 构建完整文件夹路径
        // path 格式可能是 "/disk1/folder1/folder2"，需要去掉开头的 "/"
        QString cleanPath = path;
        if (cleanPath.startsWith("/")) {
            cleanPath = cleanPath.mid(1);
        }
        
        // 构建本地文件夹路径
        QString localFolderPath = QDir(workBase).filePath(cleanPath);
        
        // 创建文件夹（如果不存在）
        QDir dir;
        if (!dir.exists(localFolderPath)) {
            if (dir.mkpath(localFolderPath)) {
                qDebug() << "SyncRootFolderCommand: 成功创建文件夹:" << localFolderPath;
                createdCount++;
            } else {
                qDebug() << "SyncRootFolderCommand: 创建文件夹失败:" << localFolderPath;
                skippedCount++;
            }
        } else {
            qDebug() << "SyncRootFolderCommand: 文件夹已存在:" << localFolderPath;
            skippedCount++;
        }
    }
    
    qDebug() << "SyncRootFolderCommand: 文件夹创建完成 - 创建:" << createdCount << "跳过:" << skippedCount;
}
